

#include <main.h>
#include <multiboot.h>
#include <debug.h>
#include <gdt.h>
#include <idt.h>
#include <process.h>
#include <lapic.h>
#include <legacy.h>
#include <pic.h>
//#include <acpi.h>
#include "../acpi/include/acpi.h"
#include <pci.h>
#include <mp.h>
#include <kmalloc.h>
#include <devmgr.h>
#include <pit.h>
#include <pmm.h>
#include <paging.h>
#include <scheduler.h>

#define __MAJOR 0
#define __MINOR 1

extern void _end_kernel;  // defined by linker at the end of the kernel

unsigned long t = 0;

void user_proc(void);

/***
 * Main entry point for the OS.
 */
int _main(multiboot_info_t *mbi, unsigned int magic)
{
	int r;
	
	cls();
	
	debugf("Panthera [%d.%d]\n", __MAJOR, __MINOR);
	
	init_gdt();  // soon enough?
	
	if (check_multiboot_magic(magic) != 0)
	{
		debugf("[BOOT] Bad Magic 0x%08x\n", magic);
		pause();
	}
	
	init_multiboot_info(mbi);
	
	init_pmm(&_end_kernel, (g_highmem*1024));
	
	init_kmalloc();
	
	init_idt();
	
	init_pic();
	
	init_mptables();
	
	init_devmgr();
	
	init_legacy();
	
	if ((r = init_pci()) != 0) {
		// error
	}
	
	/*
	if ((r = AcpiInitializeSubsystem()) != AE_OK)
	{
		debugf("[ACPI] Error Initializing Subsystem (%x)\n", r);
		for (;;) {}
	}
	
	if ((r = AcpiInitializeTables(NULL, 0, TRUE)) != AE_OK)
	{
		debugf("[ACPI] Error Initializing Tables (%x)\n", r);
	}
	
	if ((r = AcpiLoadTables()) != AE_OK)
	{
		debugf("[ACPI] Error Loading Tables (%x)\n", r);
	}
	
	*/
	
	//acpi_enum_devices();
    
    init_processes();
    
    init_scheduler();
    
    debugf("Enabling interrupts...\n");
    
	asm("sti");
	
	debugf("Enabling paging...\n");
	    	
	init_paging();
	
	pic_enable();
	
	device_t *pit = devmgr_get_device(pit_handle);
	if (pit != NULL)
	{
		pit->init();
		pit->start();
	}
	
	debugf("System tests...\n");
	
	int i;
	process_t **procs = (process_t**)kmalloc(sizeof(process_t*)*10);
	for (i = 0; i < 10; i++)
	{
		procs[i] = proc_create_process((dword*)&user_proc);
		scheduler(procs[i]->threads, procs[i]->threads->priority);
	}

	debugf("Ready!\n");
	
	for (;;) {
		debugf(".");
		asm("hlt");
	}
	
	pause();
	
	return 0;
}

void user_proc(void)
{
	int j;
	for (;;)
	{
		debugf("%d ", j++);
		asm("hlt");
	}
}
